package com.sky.handler;

import com.sky.constant.MessageConstant;
import com.sky.exception.BaseException;
import com.sky.result.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.sql.SQLIntegrityConstraintViolationException;

/**
 * 全局异常处理器，处理项目中抛出的业务异常
 */
@RestControllerAdvice
@Slf4j //日志输出
//@Slf4j是属于lombok的,@Slf4j注解为当前类提供了一个名为log的日志对象，可以在类中直接使用log对象来记录日志
public class GlobalExceptionHandler {

    /**
     * 这是一个全局异常处理器,只要是发生异常,就会捕获
     * 捕获业务异常
     * @param ex
     * @return
     */
    @ExceptionHandler  //这表示是一个异常处理器
    public Result exceptionHandler(BaseException ex){
        //BaseException这个异常也在sky-common对应的exception文件夹下,进行的定义
        //BaseException 是一个更广泛的异常类,所以这里基本上只要发生异常,就能捕获到
            //一般自定义的异常,都是继承BaseException这个异常
        log.error("异常信息：{}", ex.getMessage());
        //log表示控制台日志输出错误信息
        return Result.error(ex.getMessage());
        //返回的异常信息,getMessage这个就是BaseException自带的方法,获取到对应的异常信息
    }

    /**
     * 处理sql对应的异常
     * 这个异常,是我们在数据库确定了username是唯一的,当数据库已经存在的用户,再添加就会报这个sql对应的异常,
     *  这里通过异常处理器捕获,然后进行处理
     * @param ex
     * @return
     */
    @ExceptionHandler
    public Result exceptionHandler(SQLIntegrityConstraintViolationException ex){
        //这里的方法名和上面的一样,说明这是重载的方法,但是传入的参数是不一样的
        //获取对应的异常信息
        String message = ex.getMessage();
        if(message.contains("Duplicate entry")){
            //用来判断,这个异常信息里面是否包含"Duplicate entry"这个异常信息
            //因为后台报的这个sql异常后面的描述信息就是:Duplicate entry 'zhangsan' for key 'idx_username'
            //如果匹配上这个异常信息,那我们希望我给前端一个提示
            //提示信息: 动态的提取message中对应的用户名
            String[] split = message.split(" ");
            //通过空格来分割,因为上面异常信息,用户名被空格分割后,就是第三块内容(即对应数组的第3个元素);
            String username = split[2];  //动态的把异常信息里面的用户名取出来了
            //下面就可以拼一个提示信息(包括动态的用户名)
            String msg = username + MessageConstant.ALREADY_EXISTS;
            //这样相当于这个提示信息,就把上面的英文改成我们自己的提示信息
            //MessageConstant是一个常量类,MessageConstant.ALREADY_EXISTS就是"已存在"的意思

            //把这个提示信息,进行封装(直接用返回的result对象)
            return Result.error(msg);
        }else{
            return Result.error(MessageConstant.UNKNOWN_ERROR );   //这个常量信息表示:  "未知错误"
        }
    }

}
